package cn.thornbird.orgsync.config;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
@Slf4j
public class HttpLogger {

    @Pointcut("execution(public * cn.thornbird.orgsync.controller..*.*(..))")
    public void logPointcut() {}

    @Before("logPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String parameters = getParameters(request);
        String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        String content = String.format("uri=%s, method=%s, parameters=%s, classMethod=%s, args=%s",
                request.getRequestURI(), request.getMethod(), parameters, classMethod, args);
        log.info("REQUEST: " + content);
    }

    @AfterReturning(returning = "result", pointcut = "logPointcut()")
    public void doAfterReturning(Object result) {
        log.info("RESPONSE : " + result);
    }

    private String getParameters(HttpServletRequest request) {
        StringBuilder stringBuilder = new StringBuilder();
        Map<String, Object> paramterMap = getParameterMap(request);
        stringBuilder.append("{");
        for (Map.Entry<String, Object> entry : paramterMap.entrySet()) {
            stringBuilder.append(entry.getKey());
            stringBuilder.append("=");
            stringBuilder.append(entry.getValue());
            stringBuilder.append(";");
        }
        stringBuilder.append("}");
        return stringBuilder.toString();
    }

    private Map<String, Object> getParameterMap(HttpServletRequest request) {
        Map<String, Object> parameterMap = null;
        if (request == null) {
            return parameterMap;
        }

        Enumeration<String> enumeration = request.getParameterNames();
        parameterMap = new HashMap<>();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getParameter(key);
            parameterMap.put(key, value);
        }
        return parameterMap;
    }

}
